<?php
/**
 * 命令抽象类
 *
 * @version $Id: IAbstractCommand.php 312 2008-04-23 16:29:38Z iwind $
 * @package net.4kiki.cli
 */
abstract class IAbstractCommand extends IObject implements ICommand {
	private $parameters = array();
	private $description;
	
	/**
	 * 添加一个参数
	 *
	 * @param ICommandParameter $parameter 参数
	 */
	public function addParameter(ICommandParameter $parameter) {
		$arguments = func_get_args();
		foreach ($arguments as $argument) {
			if (is_object($argument) && get_class($argument) == "ICommandParameter") {
				$this->parameters[$argument->getName()] = $argument;
			}
		}
	}
	
	/**
	 * 取得描述
	 *
	 * @return string
	 */
	public function getDescription() {
		return $this->description;
	}
	
	/**
	 * 取得帮助文字
	 *
	 * @return string
	 */
	public function getHelp() {
		$usage = array();
		foreach ($this->parameters as $parameter) {
			$options = $parameter->getOptions();
			$optionStrings = array();
			foreach ($options as $option) {
				if ($option->isOptional()) {
					$optionStrings[] = "[" . $option->getName() . "]";
				}
				else {
					$optionStrings[] = $option->getName();
				}
			}
			if ($parameter->isOptional()) {
				$usage[] = "[" . implode(" ", $optionStrings) . " " . $parameter->getName() . "]";
			}
			else {
				$usage[] = implode(" ", $optionStrings) . " " . $parameter->getName();
			}
		}

		$usageString = "Usage: php php-command-file " . implode(" ", $usage);
		
		$optionUsage = array();
		foreach ($this->parameters as $parameter) {
			$options = $parameter->getOptions();
			foreach ($options as $option) {
				$optionUsage[] = "  " . $option->getName() . "\t  " . $option->getDescription();
			}
		}
		$optionString = implode("\n", $optionUsage);

		$help = $usageString . "\n\n" . $optionString . "\n\n" . $this->getDescription() . "\n";
		return $help;
	}
	
	/**
	 * 根据参数名取得参数
	 *
	 * @param string $parameterName 参数名
	 * @return ICommandParameter
	 */
	public function getParameter($parameterName) {
		if (isset($this->parameters[$parameterName])) {
			return $this->parameters[$parameterName];
		}
		return null;
	}
	
	/**
	 * 取得参数列表
	 *
	 * @return array
	 */
	public function getParameterMap() {
		return $this->parameters;
	}
	
	/**
	 * 设置描述
	 *
	 * @param string $description 描述
	 */
	public function setDescription($description) {
		$this->description = $description;
	}
	
	/**
	 * 从XML文件中加载参数和选项
	 *
	 * @param IFile $xmlFile XML文件对象
	 */
	public function loadFromXml(IFile $xmlFile) {
		$dom = new DOMDocument();
		$dom->load($xmlFile->getPath());
		$xpath = new DOMXPath($dom);
		$commandNodeList = $xpath->query("/command");
		if ($commandNodeList->length > 0) {
			$commandNode = $commandNodeList->item(0);
			$commandChildNodes = $commandNode->childNodes;
			if ($commandChildNodes->length > 0) {
				foreach ($commandChildNodes as $commandChildNode) {//command child node
					if ($commandChildNode->nodeType != XML_ELEMENT_NODE) {
						continue;
					}
					
					if ($commandChildNode->nodeName == "description") {
						$this->setDescription($commandChildNode->nodeValue);
					}
					else if ($commandChildNode->nodeName == "parameter-list") {
						$parameterNodes = $commandChildNode->childNodes;
						foreach ($parameterNodes as $parameterNode) {//parameter-list child node
							if ($parameterNode->nodeType != XML_ELEMENT_NODE) {
								continue;
							}
							if ($parameterNode->nodeName != "parameter") {
								continue;
							}
							$parameter = new ICommandParameter("");
							$parameterChildNodes = $parameterNode->childNodes;
							foreach ($parameterChildNodes as $parameterChildNode) { //parameter child node
								if ($parameterChildNode->nodeType != XML_ELEMENT_NODE) {
									continue;
								}
								if ($parameterChildNode->nodeName == "name") {
									$parameter->setName($parameterChildNode->nodeValue);
								}
								else if ($parameterChildNode->nodeName == "option-list") { //option-list
									$optionChildNodes = $parameterChildNode->childNodes; 
									foreach ($optionChildNodes as $optionChildNode) { // option
										if ($optionChildNode->nodeType != XML_ELEMENT_NODE) {
											continue;
										}
										if ($optionChildNode->nodeName != "option") {
											continue;
										}
										$_options = $optionChildNode->childNodes; //option's defination
										$option = new ICommandOption("");
										foreach ($_options as $_option) {
											if ($_option->nodeName == "name") {
												$option->setName($_option->nodeValue);
											}
											else if ($_option->nodeName == "description") {
												$option->setDescription($_option->nodeValue);
											}
											else if ($_option->nodeName == "optional") {
												$option->setOptional($_option->nodeValue);
											}
										}
										$parameter->addOption($option);
									}
								}
							}
							$this->addParameter($parameter);
						}
						
					}
				}
			}
		}
	}
}

?>